package cn.bugstack.springframework.aop.framework;

import cn.bugstack.springframework.aop.AdvisedSupport;
import cn.bugstack.springframework.util.ClassUtils;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 基于CGLIB2的{@link AopProxy}实现，用于Spring AOP框架。
 *
 * <p><i>需要在类路径上提供CGLIB 2.1+版本。</i>。
 * 自Spring 2.0以来，不再支持早期的CGLIB版本。
 *
 * <p>此类的对象应通过代理工厂获取，
 * 并通过AdvisedSupport对象进行配置。这是Spring AOP框架内部使用的，
 * 客户端代码不需要直接使用。
 */
public class Cglib2AopProxy implements AopProxy {

    private final AdvisedSupport advised;

    /**
     * 构造函数，初始化Cglib代理的相关配置。
     *
     * @param advised 提供代理配置的AdvisedSupport对象。
     */
    public Cglib2AopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }

    /**
     * 创建并返回一个代理对象，该对象动态地拦截目标对象的方法调用。
     *
     * @return 代理对象，该对象实现了目标对象的所有接口。
     */
    @Override
    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        Class<?> aClass = advised.getTargetSource().getTarget().getClass();
        // 确定实际的类，如果目标对象已被CGLIB代理，则使用其超类。
        aClass = ClassUtils.isCglibProxyClass(aClass)? aClass.getSuperclass():aClass;
        enhancer.setSuperclass(aClass);
        enhancer.setInterfaces(advised.getTargetSource().getTargetClass());
        // 设置方法拦截器，以实现动态代理。
        enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
        return enhancer.create();
    }

    /**
     * 动态拦截器，负责拦截目标方法的调用并执行AOP逻辑。
     */
    private static class DynamicAdvisedInterceptor implements MethodInterceptor {

        private final AdvisedSupport advised;

        /**
         * 构造函数，初始化动态拦截器。
         *
         * @param advised 提供拦截器配置的AdvisedSupport对象。
         */
        public DynamicAdvisedInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        /**
         * 拦截方法调用，根据匹配器决定是否执行拦截器链。
         *
         * @param o 目标对象。
         * @param method 被调用的方法。
         * @param objects 方法调用参数。
         * @param methodProxy 方法代理。
         * @return 方法执行结果。
         * @throws Throwable 方法执行中可能抛出的异常。
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            CglibMethodInvocation methodInvocation = new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, objects, methodProxy);
            // 如果方法匹配，则调用拦截器链。
            if (advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) {
                return advised.getMethodInterceptor().invoke(methodInvocation);
            }
            // 否则，直接调用原始方法。
            return methodInvocation.proceed();
        }
    }

    /**
     * CGLIB方法调用封装，提供一种方式来执行实际的方法调用。
     */
    private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

        private final MethodProxy methodProxy;

        /**
         * 构造函数，初始化方法调用的相关信息。
         *
         * @param target 目标对象。
         * @param method 被调用的方法。
         * @param arguments 方法调用参数。
         * @param methodProxy 方法代理。
         */
        public CglibMethodInvocation(Object target, Method method, Object[] arguments, MethodProxy methodProxy) {
            super(target, method, arguments);
            this.methodProxy = methodProxy;
        }

        /**
         * 执行方法调用。
         *
         * @return 方法执行结果。
         * @throws Throwable 方法执行中可能抛出的异常。
         */
        @Override
        public Object proceed() throws Throwable {
            return this.methodProxy.invoke(this.target, this.arguments);
        }

    }

}
